﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using Elentok.Common.Wpf.Helpers;

namespace Elentok.Common.Wpf.Controls
{
  /// <summary>
  /// This treeview class allows databinding the "SelectedObject" property
  /// </summary>
  public class EnhancedTreeView : TreeView
  {
    #region SelectedObject Dependency Property

    /// <summary>
    /// The dependency property that allows use to bind the "SelectedObject" property
    /// </summary>
    public static readonly DependencyProperty SelectedObjectProperty =
      DependencyProperty.Register("SelectedObject", typeof(object), typeof(EnhancedTreeView),
      new PropertyMetadata(SelectedObjectChangedCallback));

    /// <summary>
    /// Gets or sets the select object (a writable version of the "SelectedItem" property)
    /// </summary>
    [Bindable(true)]
    public object SelectedObject
    {
      get { return GetValue(SelectedObjectProperty); }
      set { SetValue(SelectedObjectProperty, value); }
    }

    /// <summary>
    /// This method is called whenever ever the selected object is changed,
    /// and if it was changed from the outside, this method will set the selected item.
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="eventArgs"></param>
    private static void SelectedObjectChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
    {
      EnhancedTreeView treeView = (EnhancedTreeView)obj;
      if (!ReferenceEquals(treeView.SelectedItem, eventArgs.NewValue))
        treeView.SelectItem(eventArgs.NewValue);
    }

    #endregion

    /// <summary>
    /// Searches the given item in the tree view (recursively) and selects it,
    /// returns true if the item was found and selected, false otherwise.
    /// </summary>
    /// <param name="itemToSelect"></param>
    /// <returns></returns>
    private bool SelectItem(object itemToSelect)
    {
      var treeViewItem = this.GetContainerFromItem<TreeViewItem>(itemToSelect);

      if (treeViewItem != null)
      {
        treeViewItem.Focus();
        return treeViewItem.IsSelected = true;
      }

      return false;
    }

    /// <summary>
    /// When the selected item is updated from inside the tree, this method
    /// will update the "SelectedObject" property.
    /// </summary>
    /// <param name="e"></param>
    protected override void OnSelectedItemChanged(RoutedPropertyChangedEventArgs<object> e)
    {
      this.SelectedObject = e.NewValue;

      base.OnSelectedItemChanged(e);
    }
  }
}
